package com.flashflexpro.flexdirector.agent.scriptrunner{
    import com.flashflexpro.flexdirector.agent.console.Console;
    import com.flashflexpro.flexdirector.conn.RemoteCallingEvent;
    import com.flashflexpro.flexdirector.constant.DirectorMetadata;

    import com.flashflexpro.flexdirector.model.DescProperty;

    import flash.events.EventDispatcher;
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    public class RunningStep extends EventDispatcher{
        public function RunningStep( stepX:XML, owner:RunningProcedure ){
            _stepX = stepX;

            var methodSignature:String = stepX.@name;
            _stepNum = int( methodSignature.split( "_" )[2] );
            _stepType = _stepX.metadata.arg.(@key == DirectorMetadata.metaStepType).@value;

            _stepWait = int( _stepX.metadata.arg.(@key == DirectorMetadata.metaWait).@value );
            _stepExitOnFailure = ( _stepX.metadata.arg.(@key == DirectorMetadata.metaExist).@value == "true" );
            _stepRetry = int( _stepX.metadata.arg.(@key == DirectorMetadata.metaRetry).@value );
            _owner = owner;
        }

        private var _stepNum:int;
        private var _stepType:String;

        private var _stepWait:int;
        private var _stepExitOnFailure:Boolean;
        private var _stepRetry:int;

        private var _stepX:XML;
        private var _owner:RunningProcedure;
        private var _timer:Timer;
        private var _currentErrorTime:int = 1;


        public function get stepNum():int{
            return _stepNum;
        }

        public function get stepType():String{
            return _stepType;
        }

        public function get stepX():XML{
            return _stepX;
        }

        public function get owner():RunningProcedure{
            return _owner;
        }

        public function get timer():Timer{
            return _timer;
        }

        public function get currentErrorTime():int{
            return _currentErrorTime;
        }

        private var _wait:int = -1;

        public function execute():void{
            Console.inst.stepRun( _owner.procedureClassName, _stepNum );

            if( _stepType == DirectorMetadata.metaStepTypeInput || _stepType == DirectorMetadata.metaStepTypeCheck ){
                _wait = int( _stepX.metadata.arg.(@key == DirectorMetadata.metaWait).@value );
                if( _wait > 0 ){
                    runTimer();
                    return;
                }
            }
            exeFunc();
        }

        private function exeFunc():void{
            try{
                _owner.procedure[ _stepX.@name ]();
                if( _stepType == DirectorMetadata.metaStepTypeInput ||
                        _stepType == DirectorMetadata.metaStepTypeCheck ){
                    Console.inst.stepFinish( _owner.procedureClassName, _stepNum, true );
                    _owner.onStepComplete( false );
                }
                else{
                    //running a child procedure inside the function
                }
            }
            catch( e:Error ){
                CONFIG::debugging{
                    trace( this + ".exeFunc: _stepNum[" + _stepNum + "]error:" + e.getStackTrace());
                }
                _currentErrorTime ++;

                var runnerImpl:ScriptRunnerImpl = _owner.procedure.scriptRunner as ScriptRunnerImpl;
                if( e.message == ScriptRunnerImpl.NOT_FOUND ){
                    Console.inst.stepError( _owner.procedureClassName, _stepNum, e.getStackTrace() );
                } else if( _stepType == DirectorMetadata.metaStepTypeCheck && runnerImpl.lastMemberNamePD != null ){
                    Console.inst.stepError( _owner.procedureClassName, _stepNum,
                            "Assert error, Property Name: " + runnerImpl.lastMemberNamePD.name + " " +
                                    e.getStackTrace() );
                }
                else{
                    Console.inst.stepError( _owner.procedureClassName, _stepNum,
                            "Unknown error: " + e.getStackTrace() );
                }
                if( _currentErrorTime <= _stepRetry ){
                    runTimer();
                    return;
                }
                Console.inst.stepFinish( _owner.procedureClassName, _stepNum, false );
                _owner.onStepComplete( _stepExitOnFailure );
            }
        }


        protected function onTime( ev:TimerEvent ):void{
            ( ev.target as EventDispatcher ).removeEventListener( ev.type, onTime );
            exeFunc();
        }

        private function runTimer():void{
            //todo: make this min interval frame rate related.
            _timer = new Timer( _wait > 50 ? _wait : 50, 1 );

            _timer.addEventListener( TimerEvent.TIMER_COMPLETE, onTime );
            _timer.start();
        }


    }
}